﻿/*
   Copyright 2012 University of Southampton

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
*/

using System;
using Microsoft.SharePoint;
using Microsoft.SharePoint.WebControls;
using System.Collections.Generic;
using System.Linq;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.IO;
using System.Web.UI.HtmlControls;
using uk.ac.soton.ses.DAL;
using System.Web;
using uk.ac.soton.ses.WebControls;
using uk.ac.soton.ses.UserControls;

namespace uk.ac.soton.ses.layouts
{
    public partial class ReportSelection : LayoutsPageBase
    {
        private MaterialsMetadataContext dbcontext;
        private bool IsInitialised = false;
        private bool redirect = false;
        private HashSet<int> RequestedParameterIDs = null;
        private HashSet<int> RequestedDataFileIDs = null;
        private HashSet<int> RequestedExperimentIDs = null;
        //private string reportTitle = null;
        //private string reportDescription = null;
        private ExperimentMultipleSelection _experimentSelectionControl = null;

        #region Page Life Cycle

        protected override void OnInit(EventArgs e)
        {
            base.OnInit(e);

            try
            {
                //Find the experiments quick search box, cast it, and store it in a field
                this._experimentSelectionControl = this.ctl_ExperimentMultipleSelection as ExperimentMultipleSelection;

                this.ConfigureEvents();

                //Load a database context
                this.dbcontext = HttpContext.Current.GetMaterialsDBContext();

                this.IsInitialised = true;
            }
            catch (Exception)
            {
                HDCSharedWebFunctions.AddErrorLabel("Could not load data", this.PlaceHolder_Messages);
                this.IsInitialised = false;
            }
        }

        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);

            if (this.IsInitialised)
            {
                this.ProcessQueryString();
                if (!this.IsPostBack)
                {
                    this.DatabindControls();
                    this.CreateReport();
                }
            }
        }

        protected override void OnPreRender(EventArgs e)
        {
            base.OnPreRender(e);
            if (this.redirect)
            {
                this.RedirectToNewUrl();
            }
        }

        public override void Dispose()
        {
            base.Dispose();
            if (this.dbcontext != null)
            {
                this.dbcontext.Connection.Close();
                this.dbcontext.Dispose();
            }
        }

        #endregion Page Life Cycle


        #region Private methods

        private void ProcessQueryString()
        {
            try
            {
                string[] experimentIDStrings = Page.Request.QueryString.GetValues("ExperimentID") ?? new string[0];
                IEnumerable<int> experimentIDs = experimentIDStrings.Select(id => int.Parse(id)).Distinct();
                this.RequestedExperimentIDs = new HashSet<int>(experimentIDs);

                string[] parameterIDStrings = Page.Request.QueryString.GetValues("ParameterID") ?? new string[0];
                IEnumerable<int> parameterIDs = parameterIDStrings.Select(id => int.Parse(id));
                this.RequestedParameterIDs = new HashSet<int>(parameterIDs);

                string[] datafileIDStrings = Page.Request.QueryString.GetValues("DataFileID") ?? new string[0];
                IEnumerable<int> datafileIDs = datafileIDStrings.Select(id => int.Parse(id));
                this.RequestedDataFileIDs = new HashSet<int>(datafileIDs);
            }
            catch (Exception ex)
            {
                if (ex is FormatException || ex is OverflowException || ex is ArgumentNullException)
                {
                    HDCSharedWebFunctions.AddErrorLabel("Could not parse ID", this.PlaceHolder_Messages);
                }
                if (ex is NullReferenceException)
                {
                    HDCSharedWebFunctions.AddErrorLabel("Could not find ID", this.PlaceHolder_Messages);
                }
                throw;
            }
        }

        private string CreateQueryString(string baseUrl)
        {
            IEnumerable<ListItem> selectedDataFiles = this.lst_Datafiles.Items.OfType<ListItem>().Where(li=>li.Selected);
            IEnumerable<ListItem> selectedParameters = this.lst_Parameters.Items.OfType<ListItem>().Where(li=>li.Selected);

            string experimentids = (this._experimentSelectionControl.RequestedExperimentIDs.Count > 0 ? string.Join("&", this._experimentSelectionControl.RequestedExperimentIDs.Select(id => string.Format("ExperimentID={0}", id)).ToArray()) : "");
            string reporttitle = !string.IsNullOrEmpty(this.txt_ReportTitle.Text) ? "&ReportTitle=" + HttpUtility.UrlEncode(this.txt_ReportTitle.Text) : "";
            string reportdescription = !string.IsNullOrEmpty(this.txt_ReportDescription.Text) ? "&ReportDescription=" + HttpUtility.UrlEncode(this.txt_ReportDescription.Text) : "";
            string datafiles = selectedDataFiles.Count() > 0 ? "&DataFileID=" + string.Join("&DataFileID=", selectedDataFiles.Select(li=>li.Value).ToArray()): "";
            string parameters = selectedParameters.Count() > 0 ?"&ParameterID="+ string.Join("&ParameterID=", selectedParameters.Select(li => li.Value).ToArray()) : "";
            string newUrl = string.Format("{0}?{1}{2}{3}{4}{5}", baseUrl, experimentids, reporttitle, reportdescription, datafiles, parameters);
            return newUrl;
        }

        private void CreateReport()
        {
            string newUrl = this.CreateQueryString(HDCConfiguration.Url_ReportPrintout);
            this.ctlReportPrintout.Attributes["src"] = newUrl;
        }

        private void RedirectToNewUrl()
        {
            string redirecturl = this.CreateQueryString(this.Page.Request.Url.GetLeftPart(UriPartial.Path));
            Response.Redirect(redirecturl);
        }

        private void ConfigureEvents()
        {
            this._experimentSelectionControl.ExperimentSelectionChanged += new ExperimentSelectionChangedEventHandler(this.ExperimentSelectionChanged);
            this.btn_PrintReport.Click += new EventHandler(btn_PrintReport_Click);
            this.lst_Datafiles.SelectedIndexChanged += new EventHandler(lst_Datafiles_SelectedIndexChanged);
            this.lst_Parameters.SelectedIndexChanged += new EventHandler(lst_Parameters_SelectedIndexChanged);
        }

        #endregion


        #region Event handling

        private void btn_PrintReport_Click(object sender, EventArgs e)
        {
            string redirecturl = this.CreateQueryString(HDCConfiguration.Url_ReportPrintout);
            Response.Redirect(redirecturl);
        }

        private void lst_Parameters_SelectedIndexChanged(object sender, EventArgs e)
        {
            this.redirect = true;
        }

        private void lst_Datafiles_SelectedIndexChanged(object sender, EventArgs e)
        {
            this.redirect = true;
        }

        protected void txt_ReportInfoChanged(object sender, EventArgs e)
        {
            this.redirect = true;
        }

        protected void ExperimentSelectionChanged(object sender, EventArgs e)
        {
            this.redirect = true;
        }

        #endregion


        #region Data binding

        private void DatabindControls()
        {
            this.txt_ReportTitle.Text = Page.Request.QueryString["ReportTitle"];
            this.txt_ReportDescription.Text = Page.Request.QueryString["ReportDescription"];

            this.PopulateDataFileList();
            this.PopulateParameterSelectionList();
        }


        private void PopulateDataFileList()
        {
            this.lst_Datafiles.Items.Clear();

            List<ListItem> listItems = new List<ListItem>();

            foreach (int experimentid in this._experimentSelectionControl.RequestedExperimentIDs)
            {
                foreach (ExperimentDataFile dataFile in this.dbcontext.GetExperimentDataFilesByExperimentID(experimentid, false))
                {
                    ListItem newListItem = new ListItem(dataFile.Filename, dataFile.ID.ToString());
                    newListItem.Selected = this.RequestedDataFileIDs.Contains(dataFile.ID);
                    listItems.Add(newListItem);
                }
            }
            this.lst_Datafiles.Items.AddRange(listItems.ToArray());
        }

        private void PopulateParameterSelectionList()
        {
            this.lst_Parameters.Items.Clear();

            List<ListItem> listItems = new List<ListItem>();

            foreach (int experimentid in this._experimentSelectionControl.RequestedExperimentIDs)
            {
                foreach (ExperimentParameter parameter in this.dbcontext.GetExperimentTopLevelParameters(experimentid, false))
                {
                    ListItem newListItem = new ListItem(parameter.Name, parameter.ID.ToString());
                    newListItem.Selected = this.RequestedParameterIDs.Contains(parameter.ID);
                    listItems.Add(newListItem);
                }
            }
            this.lst_Parameters.Items.AddRange(listItems.ToArray());
        }

        #endregion Data binding

    }
}
